package com.weilele.mvvm.adapter

import android.graphics.drawable.GradientDrawable
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.paging.*
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.weilele.mvvm.utils.safeGet
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers


/**
 * 创建适配器
 */
fun <Data> mvvmRcvAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
) = MvvmRcvAdapter<Data>(areItemTheSame, areContentsTheSame)


/**
 * 创建适配器
 */
fun <Data> mvvmListAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
) = MvvmListAdapter<Data>(areItemTheSame, areContentsTheSame)

/**
 * 创建适配器
 * 少量数据或者设置完数据后不会发生变化，建议优先使用[MvvmRcvAdapter]
 */
fun <Data, Holder : MvvmHolder<Data, *>> mvvmRcvAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
): MvvmRcvAdapter<Data> {
    val adapter = MvvmRcvAdapter<Data>(areItemTheSame, areContentsTheSame)
    adapter.register(holder)
    return adapter
}

/**
 * 创建适配器
 * 有大量数据，而且数据多变，建议优先使用[MvvmListAdapter]
 */
fun <Data, Holder : MvvmHolder<Data, *>> mvvmListAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否是同一组数据*/,
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null/*是否内容相同*/
): MvvmListAdapter<Data> {
    val adapter = MvvmListAdapter<Data>(areItemTheSame, areContentsTheSame)
    adapter.register(holder)
    return adapter
}

fun <Data : Any, Holder : MvvmHolder<Data, *>> mvvmPagingAdapter(
    holder: Class<Holder>,
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否是同一组数据*/
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否内容相同*/
    mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
    workerDispatcher: CoroutineDispatcher = Dispatchers.Default,
): MvvmPagingAdapter<Data> {
    val adapter =
        MvvmPagingAdapter(areItemTheSame, areContentsTheSame, mainDispatcher, workerDispatcher)
    adapter.register(holder)
    return adapter
}

/**
 * 创建适配器
 */
fun <Data : Any> mvvmPagingAdapter(
    areItemTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否是同一组数据*/
    areContentsTheSame: ((old: Data?, new: Data?) -> Boolean)? = null,/*是否内容相同*/
    mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
    workerDispatcher: CoroutineDispatcher = Dispatchers.Default,
) = MvvmPagingAdapter(areItemTheSame, areContentsTheSame, mainDispatcher, workerDispatcher)


/**
 * 基于[MvvmHolder]创建一个holder对象，如果满足不了需求，请自己继承[MvvmHolder].
 * 在同一个adapter作用域内，多次注册，找到第一个匹配[RealData],就不会再向下寻找
 */
inline fun <Data : Any?, reified RealData : Data, reified Binding : ViewBinding> IMvvmAdapter<Data>.bindHolder(
    noinline onCreateHolder: Function2<LayoutInflater, ViewGroup, MvvmHolder<RealData, Binding>>? = null/*holder创建完成监听*/,
    noinline onHolderCreated: (MvvmHolder<RealData, Binding>.() -> Unit)? = null/*holder创建完成监听*/,
    crossinline block: MvvmHolder<RealData, Binding>.(RealData) -> Unit/*绑定holder监听*/
) {
    register(RealData::class.java) { infalt, parent ->
        val bindingInstance = Binding::class.java.createViewBindingInstance(infalt, parent, false)!!
        val holder = onCreateHolder?.invoke(infalt, parent)
            ?: object : MvvmHolder<RealData, Binding>(bindingInstance) {
                override fun bindData(data: RealData) {
                    block.invoke(this, data)
                }
            }
        onHolderCreated?.invoke(holder)
        return@register holder
    }
}

/**
 * 刷新数据
 */
fun <Data> MvvmRcvAdapter<Data>.refreshList(
    newList: MutableList<Data>?,
    isReplaceDatas: Boolean = false/*newList是否替换之前的datas对象*/
) {
    submitList(newList, isReplaceDatas)
}

/**
 * 刷新数据
 */
fun <Data> MvvmListAdapter<Data>.refreshList(
    newList: MutableList<Data>?,
    commitCallback: Runnable? = null/*内部计算完差异，提交完成的回调*/
) {
    if (commitCallback == null) {
        submitList(newList)
    } else {
        submitList(newList, commitCallback)
    }
}

/**
 * 刷新数据
 */
fun <Data : Any> MvvmPagingAdapter<Data>.refreshList(
    newList: MutableList<Data>?,
    lifecycleOwner: LifecycleOwner,
) {
    submitData(lifecycleOwner.lifecycle, PagingData.from(newList ?: mutableListOf()))
}

/**
 * 讲适配器和数据源绑定
 */
fun <Data : Any, Adapter : MvvmPagingAdapter<Data>> LifecycleOwner.bindPagingAdapter(
    adapter: Adapter,
    pagingData: LiveData<PagingData<Data>>
) {
    pagingData.observe(this) {
        adapter.submitData(this@bindPagingAdapter.lifecycle, it)
    }
}

/**
 * 创建分页livedata
 */
fun <Key : Any, Value : Any> createPagingData(
    config: PagingConfig,
    initialKey: Key? = null,
    pagingSourceFactory: () -> PagingSource<Key, Value>,
): LiveData<PagingData<Value>> {
    return Pager(config, initialKey, pagingSourceFactory).liveData
}

/**
 * 创建分页livedata
 */
fun <Key : Any, Value : Any> createPagingLoadData(
    config: PagingConfig,
    initialKey: Key? = null,
    onRefreshBlock: ((state: PagingState<Key, Value>) -> Key?) = { initialKey },/*刷新的时候回调*/
    onLoadBlock: (params: PagingSource.LoadParams<Key>) -> PagingSource.LoadResult<Key, Value>,/*加载的时候回调*/
): LiveData<PagingData<Value>> {
    return createPagingData(config, initialKey, pagingSourceFactory = {
        object : PagingSource<Key, Value>() {
            override fun getRefreshKey(state: PagingState<Key, Value>): Key? {
                return onRefreshBlock.invoke(state)
            }

            override suspend fun load(params: LoadParams<Key>): LoadResult<Key, Value> {
                return onLoadBlock.invoke(params)
            }
        }
    })
}

/**
 * 通过position找到holder
 */
inline fun <reified Holder : MvvmHolder<*, *>> RecyclerView.findViewHolderForAdapterPosition(
    position: Int
): Holder? {
    return findViewHolderForAdapterPosition(position).safeGet<Holder>()
}

/**
 * 给线性布局设置分割线
 */
fun RecyclerView.addDividingWithLinearLayoutManager(
    size: Int,
    @ColorInt color: Int,
    radius: Float = 0f,
    orientation: Int = DividerItemDecoration.VERTICAL,
    startMargin: Int = 0,
    endMargin: Int = 0,
    drawLastDivider: Boolean = false,
) {
    val layoutManager = this.layoutManager
    this.addItemDecoration(
        LinearLayoutManagerDivider(
            this.context,
            if (layoutManager is LinearLayoutManager) {
                layoutManager.orientation
            } else {
                orientation
            }
        ).also {
            it.setDrawable(GradientDrawable().also { drawable ->
                drawable.setColor(color)
                drawable.cornerRadius = radius
                drawable.shape = GradientDrawable.RECTANGLE
                if (orientation == DividerItemDecoration.VERTICAL) {
                    drawable.setSize(-1, size)
                } else {
                    drawable.setSize(size, -1)
                }
            })
            it.startMargin = startMargin
            it.endMargin = endMargin
            it.drawLastDivider = drawLastDivider
        })
}